package com.gitee.deament.server.core.cli.db.sortset;

import com.gitee.deament.server.config.SystemConfig;
import com.gitee.deament.server.core.annotation.CliHander;
import com.gitee.deament.server.core.cli.AbstractCli;
import com.gitee.deament.server.core.data.ConnectData;
import com.gitee.deament.server.core.data.ZSortSet;
import com.gitee.deament.server.core.data.datatype.Value;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

import java.math.BigDecimal;
import java.util.List;

/**
 * ZCOUNT key min max
 * 可用版本： >= 2.0.0
 * 时间复杂度: O(log(N))， N 为有序集的基数。
 * 返回有序集 key 中， score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量。
 *
 * 关于参数 min 和 max 的详细使用方法，请参考 ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] 命令。
 *
 * 返回值
 * score 值在 min 和 max 之间的成员的数量。
 * @author deament
 */
@CliHander(command = "ZCOUNT")
public class ZCOUNTcli extends AbstractCli {
    @Override
    public void executeCli(ChannelHandlerContext channelHandlerContext, String command) {
        List<String> cliValues = getValues(command);
        if (cliValues.size() !=4) {
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame("ERR wrong number of arguments for 'ZCARD' command"));
            return;
        }
        String key = cliValues.get(1);
        String min = cliValues.get(2);
        String max = cliValues.get(3);

        int db = ConnectData.SELECT_DB_STORAGE.getUseDB(channelHandlerContext.channel().id().asLongText());
        try {
            BigDecimal minValue= new BigDecimal(min);
            BigDecimal maxValue= new BigDecimal(max);

            Value<ZSortSet> zSortSetData = SystemConfig.dbData.getZSortSetData(db, key);
            if(zSortSetData==null ||zSortSetData.getValue()==null ||zSortSetData.getValue().getData()==null){
                channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame("0"));
                return;
            }
            long count = zSortSetData.getValue().getData().stream().filter(x -> x.getScore().compareTo(minValue) > -1 && x.getScore().compareTo(maxValue) < 1).count();

            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(count+""));
            return;

        }catch (Exception e){
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(e.getMessage()));
            return;
        }
    }
}
